# This file is part of OrangeSpider. OrangeSpider is a meta model based
# development tool.
# 
# OrangeSpider is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# OrangeSpider is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with OrangeSpider.  If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2009 Stefan Nikolaus <OrangeSpiderMaster@googlemail.com>

from pysqlite2 import dbapi2 as sqlite
import os
import MetaModel
import Algorithms
import Interface
import Builder 
import Types
#"Data/TestSQL/DB1.db"

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import Ui
import sys

class Boolean(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        if o.value:
            return str(1)
        else:
            return str(0)
    @staticmethod
    def convert(value):
        if int(value):
            return Boolean(True)
        else:
            return Boolean(False)

class Picture(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return buffer(o.value)
    @staticmethod
    def convert(value):
        return Picture(value)

class Text(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return Text(value)

class Blob(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return buffer(o.value)
    @staticmethod
    def convert(value):
        return Picture(value)


class DateTime(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return "%d,%d,%d,%d,%d,%d" % o.value
    @staticmethod
    def convert(value):
        t = map(int, value.split(","))
        return DateTime(tuple(t))

class TimeStamp(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return TimeStamp(value)

class Color(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return "%d,%d,%d,%d" % o.value
    @staticmethod
    def convert(value):
        t = map(int, value.split(","))
        return Color(tuple(t))

class Font(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return Font(value)

class FileString(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return FileString(value)

class Directory(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return Directory(value)

class Size(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return "%d,%d" % o.value
    @staticmethod
    def convert(value):
        t = map(float, value.split(","))
        return Size(tuple(t))

class Point(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return "%d,%d" % o.value
    @staticmethod
    def convert(value):
        t = map(float, value.split(","))
        return Point(tuple(t))


class Rect(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return "%d,%d,%d,%d" % o.value
    @staticmethod
    def convert(value):
        t = map(float, value.split(","))
        return Rect(tuple(t))

class Flags(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return Flags(value)


class Url(object):
    def __init__(self, value):
        self.value = value
    @staticmethod
    def adapt(o):
        return str(o.value)
    @staticmethod
    def convert(value):
        return Url(value)


sqlite.register_adapter(Boolean, Boolean.adapt)
sqlite.register_adapter(Picture, Picture.adapt)
sqlite.register_adapter(Text, Text.adapt)
sqlite.register_adapter(DateTime, DateTime.adapt)
sqlite.register_adapter(TimeStamp, TimeStamp.adapt)
sqlite.register_adapter(Color, Color.adapt)
sqlite.register_adapter(Font, Font.adapt)
sqlite.register_adapter(Blob, Blob.adapt)
sqlite.register_adapter(FileString, FileString.adapt)
sqlite.register_adapter(Directory, Directory.adapt)
sqlite.register_adapter(Size, Size.adapt)
sqlite.register_adapter(Point, Point.adapt)
sqlite.register_adapter(Rect, Rect.adapt)
sqlite.register_adapter(Flags, Flags.adapt)
sqlite.register_adapter(Url, Url.adapt)

# Register the converter
sqlite.register_converter("BOOLEAN", Boolean.convert)
sqlite.register_converter("PICTURE", Picture.convert)
sqlite.register_converter("TEXT", Text.convert)
sqlite.register_converter("DATETIME", DateTime.convert)
sqlite.register_converter("TIMESTAMP", TimeStamp.convert)
sqlite.register_converter("COLOR", Color.convert)
sqlite.register_converter("FONT", Font.convert)
sqlite.register_converter("BLOB", Blob.convert)
sqlite.register_converter("FILESTRING", FileString.convert)
sqlite.register_converter("DIRECTORY", Directory.convert)
sqlite.register_converter("SIZE", Size.convert)
sqlite.register_converter("POINT", Point.convert)
sqlite.register_converter("RECT", Rect.convert)
sqlite.register_converter("FLAGS", Flags.convert)
sqlite.register_converter("URL", Url.convert)


typeMap = {}
typeMap["Boolean"] = Boolean
typeMap["Picture"] = Picture
typeMap["DateTime"] = DateTime
typeMap["TimeStamp"] = TimeStamp
typeMap["Color"] = Color
typeMap["Font"] = Font
typeMap["FileString"] = FileString
typeMap["Directory"] = Directory
typeMap["Size"] = Size
typeMap["Point"] = Point
typeMap["Rect"] = Rect
typeMap["Flags"] = Flags
typeMap["Url"] = Url
typeMap["Text"] = Text
typeMap["Blob"] = Blob
#typeMap["String"] = ""
#typeMap["Integer"] = ""
#typeMap["Float"] = ""


Types.mappings["SQLiteConverter"] = typeMap

def _buildTableName(me):
    return "[%s] " % me["Name"]

class TableCreatorVisitor:
    def __init__(self, con):
        # store the sqlite connection
        self.con = con
    def _execute(self, sql):
        #print sql
        cur = self.con.cursor()
        cur.execute(sql)
        
    def visitMetaModel(self, mm):
        s = ""
        
        s += "CREATE TABLE _MetaModel"
        s += "("
        s += "  Id LONG PRIMARY KEY"
        s += ", Name STRING"
        s += ", Type STRING"
        s += ", Description STRING"
        s += ", FileName STRING"
        s += ", UUID STRING"
        s += ", MajorVersion INTEGER"
        s += ", MinorVersion INTEGER"
        s += ", Icon PICTURE"
        s += ", CurrentId LONG"
        s += ")"
        self._execute(s)
        
        s =  "CREATE TABLE _MetaType"
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaModel_Id INTEGER"
        s += ", Name STRING"
        s += ", Description STRING"
        s += ", DefaultValue STRING"
        s += ", IsEnum BOOLEAN"
        s += ")"
        self._execute(s)

        s =  "CREATE TABLE _MetaAtom"
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", Name STRING"
        s += ", MetaType_Id INTEGER"
        s += ", Description STRING"
        s += ")"
        self._execute(s)

        s =  "CREATE TABLE _MetaClass"
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaModel_Id INTEGER"
        s += ", Name STRING"
        s += ", Description STRING"
        s += ", Icon PICTURE"
        s += ", ExtensionTableName STRING"
        s += ")"
        self._execute(s)

        s =  "CREATE TABLE _MetaAssoc"
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaModel_Id INTEGER"
        s += ", Name STRING"
        s += ", Description STRING"
        s += ", SourceName STRING"
        s += ", TargetName STRING"
        s += ", AssocName STRING"
        s += ", SourceCardinality STRING"
        s += ", TargetCardinality STRING"
        s += ", Aggregation INTEGER"
        s += ", Icon PICTURE"
        s += ", ExtensionTableName STRING"
        s += ")"
        self._execute(s)

        s =  "CREATE TABLE _MetaProperty"
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaEntity_Id INTEGER"
        s += ", MetaType_Id INTEGER"
        s += ", Name STRING"
        s += ", Description STRING"
        s += ", IsUnique BOOLEAN"
        s += ", IsIdentifying BOOLEAN"
        s += ")"
        self._execute(s)

    def visitMetaClass(self, mc):
        s =  "CREATE TABLE " + _buildTableName(mc)
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaClass_Id INTEGER"
        s += self.buildColumnDecl(mc)
        s += ")"
        self._execute(s)

    def visitMetaAssoc(self, ma):
        s =  "CREATE TABLE " + _buildTableName(ma)
        s += "("
        s += "  Id INTEGER PRIMARY KEY"
        s += ", MetaAssoc_Id INTEGER"
        s += ", Source_Id INTEGER"
        s += ", Target_Id INTEGER"
        s += self.buildColumnDecl(ma)
        s += ")"
        self._execute(s)

    def visitMetaProperty(self, mp):
        pass
    def visitMetaType(self, mt):
        pass
    def visitMetaAtom(self, mat):
        pass
    def visitClass(self, c):
        pass
    def visitAssoc(self, a):
        pass
    
    def buildColumnDecl(self, me):
        s = ""
        for mp in me.eachMetaProperty():
            if mp["Name"] != "Id":
                if mp.metaType.isMetaEnum():
                    s += ", [" + mp["Name"] + "] " + "STRING"
                else:
                    s += ", [" + mp["Name"] + "] " + mp.metaType["Name"].upper()
        return s
      
        
class InserterVisitor:
    def __init__(self, con):
        # store the sqlite connection
        self.con = con
        self.currentMetaModelId = 0
        self.currentMetaEntityId = 0
        self.currentMetaPropertyId = 0
        self.currentMetaTypeId = 0
        self.currentMetaAtomId = 0
        self.metaTypeIds = {}
    def _execute(self, sql, data):
        cur = self.con.cursor()
        assert(type(data) == tuple)
        #print sql, data
        assert(type(sql) == str or type(sql) == unicode)
        cur.execute(sql, data)
    def visitMetaModel(self, mm):
        s =  "INSERT INTO _MetaModel(Id, Name, Type, Description, FileName, UUID, MajorVersion, MinorVersion, Icon, CurrentId)"
        s += " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        self.currentMetaModelId = 1
        self._execute(s, (self.currentMetaModelId,
                         mm["Name"], mm["Type"], mm["Description"], mm["FileName"],
                         mm["UUID"], mm["MajorVersion"], mm["MinorVersion"],
                         Picture(mm["Icon"]), mm.currentId))
        
    def visitMetaClass(self, mc):
        s =  "INSERT INTO _MetaClass(Id, MetaModel_Id, Name, Description, Icon, ExtensionTableName)"
        s += " VALUES (?, ?, ?, ?, ?, ?)"
        self.currentMetaEntityId += 1
        self._execute(s, (self.currentMetaEntityId,
                         self.currentMetaModelId,
                         mc["Name"], mc["Description"], Picture(mc["Icon"]),
                         _buildTableName(mc)))

    def visitMetaAssoc(self, ma):
        s =  "INSERT INTO _MetaAssoc(Id, MetaModel_Id, Name, Description, SourceName, TargetName, AssocName, SourceCardinality, TargetCardinality, Aggregation, Icon, ExtensionTableName)"
        s += " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        self.currentMetaEntityId += 1

        self._execute(s, (self.currentMetaEntityId,
                         self.currentMetaModelId,
                         ma["Name"], ma["Description"], ma["SourceName"],
                         ma["TargetName"], ma["AssocName"],
                         ma["SourceCardinality"], ma["TargetCardinality"],
                         Boolean(ma["Aggregation"]),
                         Picture(ma["Icon"]),
                         _buildTableName(ma)))
    def visitMetaProperty(self, mp):
        s =  "INSERT INTO _MetaProperty(Id, MetaEntity_Id, MetaType_Id, Name, Description, IsUnique, IsIdentifying)"
        s += " VALUES (?, ?, ?, ?, ?, ?, ?)"
        self.currentMetaPropertyId += 1
        metaTypeId = self.metaTypeIds[mp.metaType["Name"]]
        self._execute(s, (self.currentMetaPropertyId,
                         self.currentMetaEntityId,
                         metaTypeId,
                         mp["Name"],
                         mp["Description"],
                         Boolean(mp["IsUnique"]),
                         Boolean(mp["IsIdentifying"])))
        
    def visitMetaType(self, mt):
        s =  "INSERT INTO _MetaType(Id, MetaModel_Id, Name, Description, DefaultValue, IsEnum)"
        s += " VALUES (?, ?, ?, ?, ?, ?)"
        self.currentMetaTypeId += 1
        self._execute(s, (self.currentMetaTypeId,
                         self.currentMetaModelId,
                         mt["Name"], mt["Description"],
                         str(mt["DefaultValue"]), Boolean(mt.isMetaEnum())))
        self.metaTypeIds[mt["Name"]] = self.currentMetaTypeId
    def visitMetaAtom(self, mat):
        s =  "INSERT INTO _MetaAtom(Id, MetaType_Id, Name, Description)"
        s += " VALUES (?, ?, ?, ?)"
        self.currentMetaAtomId += 1
        self._execute(s, (self.currentMetaAtomId,
                         self.currentMetaTypeId,
                         mat["Name"], mat["Description"]))
    def visitClass(self, c):
        mc = c.intention
        s =  "INSERT INTO " + _buildTableName(mc)
        s += "(Id, MetaClass_Id"
        s += self.buildColumnDecl(c, "Columns")
        s += ") VALUES (?, ?"
        s += self.buildColumnDecl(c, "Placeholder")
        s += ")"
        self._execute(s, self.buildColumnDecl(c, "Data"))
        
    def visitAssoc(self, a):
        ma = a.intention
        s =  "INSERT INTO " + _buildTableName(ma)
        s += "(Id, MetaAssoc_Id, Source_Id, Target_Id"
        s += self.buildColumnDecl(a, "Columns")
        s += ") VALUES (?, ?, ?, ?"
        s += self.buildColumnDecl(a, "Placeholder")
        s += ")"
        self._execute(s, self.buildColumnDecl(a, "Data"))

    def buildColumnDecl(self, entity, group):
        me = entity.intention
        if group == "Columns":
            s = ""
            for mp in me.eachMetaProperty():
                if mp["Name"] != "Id":
                    s += ", [" + mp["Name"] + "]"
        elif group == "Placeholder":
            s = ""
            for mp in me.eachMetaProperty():
                if mp["Name"] != "Id":
                    s += ", ?"
        elif group == "Data":
            s = (entity["Id"], self.currentMetaEntityId)
            if me.isMetaAssoc():
                s += (entity.source["Id"], entity.target["Id"])
            for mp in me.eachMetaProperty():
                if mp["Name"] != "Id":
                    name = mp["Name"]
                    metaType = mp.metaType["Name"]
                    if metaType in typeMap:
                        converterClass = typeMap[metaType]
                        # Let a convert class do the conversion
                        s += (converterClass(entity[name]), )
                    else:
                        # Do not convert the value, it is a
                        # simple sqlite type
                        s += (entity[name], )

        else:
            assert(0)
        return s

"""
The creator imports a meta model from a sqlite database
"""
class Creator:
    def __init__(self, con):
        self.con = con
        con.row_factory = sqlite.Row 
        self.mm = None
        self.metaModelId = 0
        self.withMetaLayer = False
        self.metaTypeMap = {}
        
    def read(self):
        self._readMetaModel()

    def _execute(self, sql, data = None):
        assert(type(sql) == str)
        cur = self.con.cursor()
        if data:
            assert(type(data) == tuple)
            cur.execute(sql, data)
        else:
            cur.execute(sql)
        return cur
    
    def _readMetaModel(self):
        s = "SELECT"
        s += "  Id"
        s += ", Name"
        s += ", Type"
        s += ", Description"
        s += ", FileName"
        s += ", UUID"
        s += ", MajorVersion"
        s += ", MinorVersion"
        s += ", Icon"
        s += ", CurrentId"
        s += " FROM _MetaModel"
        cur = self._execute(s)
        for row in cur:
            mm = MetaModel.MetaModel(row["Name"], row["Type"], MetaModel.Watcher())
            mm["Description"] = row["Description"]
            mm["FileName"] = row["FileName"]
            mm["UUID"] = row["UUID"]
            mm["MajorVersion"] = row["MajorVersion"]
            mm["MinorVersion"] = row["MinorVersion"]
            mm["Icon"] = row["Icon"].value
            mm.currentId = row["CurrentId"]
            self.mm = mm
            self.metaModelId = row["Id"]

        self._readMetaTypes()
        self._readMetaClasses()
        self._readMetaAssocs()

    def _readMetaTypes(self):
        s = "SELECT "
        s += "  Id"
        s += ", MetaModel_Id"
        s += ", Name"
        s += ", Description"
        s += ", DefaultValue"
        s += ", IsEnum"
        s += " FROM _MetaType WHERE MetaModel_Id = ?"

        cur = self._execute(s, (self.metaModelId,) )
        for row in cur:
            if row["IsEnum"].value:
                mt = self.mm.MetaEnum(row["Name"], str(row["DefaultValue"]), row["Description"])
                self._readMetaAtoms(mt, row["Id"])
            else:
                mt = self.mm.MetaType(row["Name"], str(row["DefaultValue"]),  row["Description"])
            self.metaTypeMap[row["Id"]] = mt

    def _readMetaAtoms(self, me, metaTypeId):
        s = "SELECT "
        s += "  Id"
        s += ", Name"
        s += ", MetaType_Id"
        s += ", Description"
        s += " FROM _MetaAtom WHERE MetaType_Id = ?"

        cur = self._execute(s, (metaTypeId,) )
        for row in cur:
            ma = self.mm.MetaAtom(me["Name"], row["Name"], row["Description"])

    def _readMetaClasses(self):
        s = "SELECT "
        s += "  Id"
        s += ", MetaModel_Id"
        s += ", Name"
        s += ", Description"
        s += ", Icon"
        s += ", ExtensionTableName"
        s += " FROM _MetaClass WHERE MetaModel_Id = ?"
        cur = self._execute(s, (self.metaModelId,) )
        for row in cur:
            mc = self.mm.MetaClass(row["Name"], row["Description"])
            mc["Icon"] = row["Icon"].value
            self._readMetaProperties(mc, row["Id"])
            self._readClass(mc, row["Id"], row["ExtensionTableName"])

    def _readClass(self, mc, metaClassId, table):
        s = "SELECT "
        s += self._buildColumnDecl(mc)
        s += " FROM %s WHERE MetaClass_Id = ?" % (str(table),)
        cur = self._execute(s, (metaClassId,) )
        for row in cur:
            c = self.mm.Class(mc["Name"], row["Id"])
            self._setProperties(mc, c, row)
                              
    def _readMetaAssocs(self):
        s = "SELECT "
        s += "  Id"
        s += ", MetaModel_Id"
        s += ", Name"
        s += ", Description"
        s += ", SourceName"
        s += ", TargetName"
        s += ", AssocName"
        s += ", SourceCardinality"
        s += ", TargetCardinality"
        s += ", Aggregation"
        s += ", Icon"
        s += ", ExtensionTableName"
        s += " FROM _MetaAssoc WHERE MetaModel_Id = ?"
        cur = self._execute(s, (self.metaModelId,) )
        for row in cur:
            ma = self.mm.MetaAssoc(row["Name"], row["Description"])
            ma["Icon"] = row["Icon"].value
            ma["SourceCardinality"] = row["SourceCardinality"]
            ma["TargetCardinality"] = row["TargetCardinality"]
            ma["Aggregation"] = row["Aggregation"]
            self._readMetaProperties(ma, row["Id"])
            self._readAssoc(ma, row["Id"], row["ExtensionTableName"])

    def _readAssoc(self, ma, metaClassId, table):
        s = "SELECT "
        s += self._buildColumnDecl(ma)
        s += ", Source_Id"
        s += ", Target_Id"
        s += " FROM %s WHERE MetaAssoc_Id = ?" % (str(table),)
        cur = self._execute(s, (metaClassId,) )
        for row in cur:
            source = self.mm.access(MetaModel.Entity.CLASS,
                                    (ma["SourceName"], row["Source_Id"]))
            target = self.mm.access(MetaModel.Entity.CLASS,
                                    (ma["TargetName"], row["Target_Id"]))
            a = self.mm.Assoc(source, target, ma["Name"], row["Id"])
            self._setProperties(ma, a, row)

    def _setProperties(self, me, c, row):
        for mp in me.eachMetaProperty():
            mpName = str(mp["Name"])
            metaTypeName = mp.metaType["Name"]
            if mpName != "Id":
                if metaTypeName in typeMap:
                    c[mpName] = row[mpName].value
                else:
                    c[mpName] = row[mpName]
            
    def _readMetaProperties(self, mc, metaEntityId):
        s = "SELECT "        
        s += "  Id"
        s += ", MetaEntity_Id"
        s += ", MetaType_Id"
        s += ", Name"
        s += ", Description"
        s += ", IsUnique"
        s += ", IsIdentifying"
        s += " FROM _MetaProperty WHERE MetaEntity_Id = ?"
        cur = self._execute(s, (metaEntityId,) )
        for row in cur:
            metaType = self.metaTypeMap[row["MetaType_Id"]]
            mp = self.mm.MetaProperty(mc["Name"], row["Name"], metaType["Name"],
                                      row["Description"])
            mp["IsUnique"] = row["IsUnique"].value
            mp["IsIdentifying"] = row["IsIdentifying"].value

    def _buildColumnDecl(self, me):
        s = ""
        sep = "  "
        for mp in me.eachMetaProperty():
            s += sep + "[" + str(mp["Name"]) + "]"
            sep = ", "
        return s
#
#MetaAssoc
#
#metaProperty
#Id
#MetaEntity_Id
#MetaType_Id
#Name
#Description
#IsUnique
#IsIdentifying

# Writing metamodel
class Exporter:
    def __init__(self, r = None):
        self.metaModel = r
        
    def save(self, filename):
        con = None
        try: 
            path = filename
            self._removeFile(path)

            con = sqlite.connect(filename,
                                 detect_types = sqlite.PARSE_DECLTYPES)
            r = self.metaModel

            # Create tables
            v = TableCreatorVisitor(con)
            w = Algorithms.Walker(r, v)
            w.fullWalk()

            # insert data into the tables
            v = InserterVisitor(con)
            w = Algorithms.Walker(r, v)
            w.fullWalk()
            con.commit()
        except sqlite.Error, e:
            print str(e)
            con.rollback()
        con.close()

    def _removeFile(self, path):
        try:
            os.remove(path)
        except OSError, e:
            pass

#Importer
# Flag: with MM: j/n
# Reading metamodel
class Importer:
    def __init__(self):
        self.metaModel = None
    def load(self, filename):
        con = None
        try:
            con = sqlite.connect(filename,
                                 detect_types=sqlite.PARSE_DECLTYPES)
            c = Creator(con)
            c.read()
            
            c.mm.watcher = MetaModel.Watcher()
            c.mm.watcher.addListener(Ui.Emitter(), "Emitter")
            self.metaModel = c.mm
        finally:
            if con:
                con.close()
        return self.metaModel
        
def doTest4():
    r = MetaModel.buildMetaModel("Test", "SpiderTST", MetaModel.Watcher())
    Algorithms.randomFill(r, 10)
    r.watcher.addListener(Ui.Emitter(), "Emitter")

    app = QApplication(sys.argv)
    mb = Ui.MatrixWidget(r)
    mb.exec_()

    # Export it
    ex = Exporter(r)
    ex.save("D:/Users/sn/Development/Repository/Data/TestSQL/DB1.sqlite")

    r = None

    im = Importer()
    r = im.load("D:/Users/sn/Development/Repository/Data/TestSQL/DB1.sqlite")
    mb = Ui.MatrixWidget(r)
    mb.exec_()

    ex = Exporter(r)
    ex.save("D:/Users/sn/Development/Repository/Data/TestSQL/DB1.sqlite")
    
    r = None

    im = Importer()
    r = im.load("D:/Users/sn/Development/Repository/Data/TestSQL/DB1.sqlite")
    mb = Ui.MatrixWidget(r)
    mb.exec_()

def doTest3():
    try:
        con = sqlite.connect("Data/TestSQL/db2.sqlite", detect_types=sqlite.PARSE_DECLTYPES)
        c = Creator(con)
        c.read()

        c.mm.watcher = MetaModel.Watcher()
        c.mm.watcher.addListener(Ui.Emitter(), "Emitter")

        app = QApplication(sys.argv)
        mb = Ui.MatrixWidget(c.mm)
        mb.exec_()

    finally:
        con.close()
    
def doTest2():
    try: 
        path = "Data/TestSQL/db2.sqlite"
        try:
            os.remove(path)
        except OSError, e:
            pass
        con = sqlite.connect("Data/TestSQL/db2.sqlite", detect_types=sqlite.PARSE_DECLTYPES)
        im = MetaModel.Importer()
        r = im.load("D:/Users/sn/Development/Repository/Data/TestSpider/Test1/Test1.spid")
        v = TableCreatorVisitor(con)
        w = Algorithms.Walker(r, v)
        w.fullWalk()
        con.commit()

        v = InserterVisitor(con)
        w = Algorithms.Walker(r, v)
        w.fullWalk()
        con.commit()
    finally:
        con.close()
    
def doTest():
    print "doTest"
    path = "Data/TestSQL/DB1.db"
    try:
        os.remove(path)
    except OSError, e:
        pass

    con = sqlite.connect(path)
    con.execute("create table [per.son](firstname TEXT, lastname TEXT, [Order] STRING ) ")
    con.execute("insert into [per.son](firstname, lastname) values (?, ?)",
                ("a", "b"))
    con.execute("insert into [per.son](firstname, lastname) values (?, ?)",
                ("a", "b"))
    con.execute("insert into [per.son](firstname, lastname) values (?, ?)",
                ("a", "b"))
    con.execute("insert into [per.son](firstname, lastname) values (?, ?)",
                ("a", "b"))
    con.execute("insert into [per.son](firstname, lastname) values (?, ?)",
                ( "(1.0, 2.0)" , "b"))
    con.commit()
    con.close()

    con = sqlite.connect(path)
    cur = con.cursor()
    cur.execute("select [firstname], [lastname], [order] from [per.son]")
    print cur.fetchall()
    for row in cur:
        print row["firstname"]
    con.close()
    
if __name__ == "__main__":
    doTest4()

    #im = MetaModel.Importer()
    #r = im.load("D:/Users/sn/Development/Repository/Data/TestSpider/CodeMeter/CodeMeter.spid")

    #v = ExporterVisitor()
    #w = Algorithms.Walker(r, v)
    #w.fullWalk()
    
